package com.example.demo.adapter;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import com.example.demo.dto.NettyHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import com.example.demo.dto.Action;
import com.example.demo.dto.NettyHttpRequest;

/**
 * 请求分排器
 */
@Component
public class RequestDispatcher {

	@Autowired
	private ApplicationContext context;
	
	@Autowired
	private RequestMappingHandlerMapping mapping;
	
	private static final Map<String,Action> urlMapping = new ConcurrentHashMap<String, Action>();
	
	public void initAllUrl() {
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        for (Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
            Action action = new Action();
        	RequestMappingInfo info = m.getKey();
            HandlerMethod method = m.getValue();
            PatternsRequestCondition p = info.getPatternsCondition();
            for (String url : p.getPatterns()) {
            	action.setUrl(url);
            }

            action.setClazz(context.getBean(method.getBean().toString()));
            action.setMethod(method.getMethod());
            RequestMethodsRequestCondition methodsCondition = info.getMethodsCondition();
            for (RequestMethod requestMethod : methodsCondition.getMethods()) {
            	action.setRequestMethod(requestMethod);
            }
            urlMapping.put(action.getUrl(), action);
        }
	}
	
	/**
	 * 反射调用spring bean方法的入口
	 * @throws Exception
	 */
	public Object dispatcher(NettyHttpRequest request) throws Exception {
		Action action = getRoute(request);
		if(null == action){
			return NettyHttpResponse.make(HttpResponseStatus.NOT_FOUND);
		}
		// 获取代理对象（可能被JDK或者CGLIB代理）
		Object proxyObject = action.getClazz();
		// 获取代理对象执行的方法
		Method method = action.getMethod();
		// 执行方法
		return method.invoke(proxyObject);
	}

	private Action getRoute(NettyHttpRequest request) {
		String url = request.getUri();
		return urlMapping.get(url.split("\\?")[0]);
	}


}